﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace YArchitech.Plumbing.Model
{
	public static class Algorithm
	{
		public static List<Line> CombineCollineationLines(List<Line> lines, double tolerance)
		{
			List<Line> list = new List<Line>();
			List<Line> list2 = new List<Line>();
			for (int i = 0; i < lines.Count; i++)
			{
				if (!list2.Contains(lines[i]))
				{
					for (int j = i + 1; j < lines.Count; j++)
					{
						if (!list2.Contains(lines[j]))
						{
							Line combinationLine = Algorithm.GetCombinationLine(lines[i], lines[j], tolerance);
							if (combinationLine != null)
							{
								list.Add(combinationLine);
								list2.Add(lines[i]);
								list2.Add(lines[j]);
							}
						}
					}
				}
			}
			if (list2.Count > 0)
			{
				foreach (Line item in list2)
				{
					lines.Remove(item);
				}
				foreach (Line item2 in list)
				{
					lines.Add(item2);
				}
				Algorithm.CombineCollineationLines(lines, tolerance);
			}
			return lines;
		}

		public static Line GetCombinationLine(Line line1, Line line2, double tolerance)
		{
			Line result = null;
			try
			{
				if (new YJKLine(line1).IsLineOnLine(line2))
				{
					List<XYZ> list = new List<XYZ>();
					List<XYZ> list2 = new List<XYZ>();
					if (Algorithm.GetExtremeLineDistance(line1, line2, list, list2))
					{
						IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
						SetComparisonResult setComparisonResult = line1.Intersect(line2, out intersectionResultArray);
						if ((setComparisonResult == SetComparisonResult.Equal || setComparisonResult == SetComparisonResult.Subset || setComparisonResult == SetComparisonResult.Superset) && list2.Count == 2)
						{
							result = Line.CreateBound(list2[0], list2[1]);
						}
						if ((int)setComparisonResult == 4 && list.Count == 2 && list[0].DistanceTo(list[1]) <= tolerance)
						{
							result = Line.CreateBound(list2[0], list2[1]);
						}
					}
				}
			}
			catch (Exception ex)
			{
				ex.ToString();
			}
			return result;
		}

		public static bool GetExtremeLineDistance(Line line1, Line line2, List<XYZ> minDisPoints, List<XYZ> maxDisPoints)
		{
			bool result = false;
			try
			{
				List<XYZ> list = new List<XYZ>();
				list.Add(line1.GetEndPoint(0));
				list.Add(line1.GetEndPoint(1));
				list.Add(line2.GetEndPoint(0));
				list.Add(line2.GetEndPoint(1));
				double num = double.MaxValue;
				double num2 = double.MinValue;
				for (int i = 0; i < list.Count; i++)
				{
					for (int j = i + 1; j < list.Count; j++)
					{
						double num3 = list[i].DistanceTo(list[j]);
						if (num3 < num && (i + j) % 2 == 0)
						{
							num = num3;
							minDisPoints.Clear();
							minDisPoints.Add(list[i]);
							minDisPoints.Add(list[j]);
						}
						if (num3 > num2)
						{
							num2 = num3;
							maxDisPoints.Clear();
							maxDisPoints.Add(list[i]);
							maxDisPoints.Add(list[j]);
						}
					}
				}
				result = true;
			}
			catch (Exception ex)
			{
				ex.ToString();
			}
			return result;
		}
	}
}
